#include <unistd.h>
#include <sys/time.h>
#include "seqiot.h"
#include "channel.h"
#include "dlt645_acquire.h"

void sched_dlt645_device(channel_t *channel, data_catalog_e catalog, device_t *device) {
    int rc, i;
    segment_e segments[] = {seg_do, seg_di, seg_ao, seg_ai};

    if (!is_retry_sched(device)) {
        return;
    }

    rc = dlt645_init(channel, device);
    update_stats(device, channel, rc);
    if (rc < 0) {
        log_warn("failed to detect online status for dlt645 %d/%s", device->super.id, device->super.name);
        return;
    }

    for (i = 0; i < sizeof(segments) / sizeof(segments[0]); ++i) {
        vector_t *tag_list = &device->_product->thing_model[segments[i]];
        if (0 == vector_size(tag_list)) {
            continue;
        }

        for (i = 0; i < vector_size(tag_list); ++i) {
            thing_model_t *tag = vector_get(tag_list, i);

            if (tag->catalog != catalog) {
                continue;
            }

            rc = dlt645_collect(channel, device, tag);
            update_stats(device, channel, rc);
        }
    }
}

void sched_dlt645_channel(channel_t *channel, data_catalog_e catalog) {
    int i;

    for (i = 0; i < vector_size(&channel->devices); ++i) {
        device_t *device = vector_get(&channel->devices, i);

        sched_dlt645_device(channel, catalog, device);
    }
}

void sched_dlt645_catalogs(channel_t *channel, seqiot_t *seqiot) {
    int i;

    struct timeval _tv;
    gettimeofday(&_tv, NULL);

    for (i = 0; i < vector_size(&seqiot->catalogs); ++i) {
        data_catalog_t *catalog = vector_get(&seqiot->catalogs, i);

        if (catalog->_next_sched && catalog->_next_sched <= _tv.tv_sec) {
            catalog->_next_sched = next_sched(_tv.tv_sec, &catalog->read);

            struct tm _tm;
            localtime_r(&catalog->_next_sched, &_tm);
            log_debug("next=%04d-%02d-%02d %02d:%02d:%02d, catalog=%d, period=%d, delay=%d",
                      _tm.tm_year + 1900, _tm.tm_mon + 1, _tm.tm_mday, _tm.tm_hour, _tm.tm_min, _tm.tm_sec,
                      catalog->catalog, catalog->read.period, catalog->read.delay);

            sched_dlt645_channel(channel, catalog->catalog);
        }
    }

    gettimeofday(&_tv, NULL);
    usleep(1000 * 1000L - _tv.tv_usec);
}

void sched_dlt645(channel_t *channel, seqiot_t *seqiot) {
    int i;

    struct timeval _tv;
    gettimeofday(&_tv, NULL);
    //必须调用一次__timezone才有值
    localtime(&_tv.tv_sec);

    for (i = 0; i < vector_size(&seqiot->catalogs); ++i) {
        data_catalog_t *catalog = vector_get(&seqiot->catalogs, i);
        if (catalog->read.period < 0) {
            catalog->_next_sched = _tv.tv_sec;
        } else {
            catalog->_next_sched = next_sched(_tv.tv_sec, &catalog->read);
        }
    }

    while (running) {
        sched_dlt645_catalogs(channel, seqiot);
    }
}
